package com.himiotech.core.project.helper.utils;

import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.template.Template;
import cn.hutool.extra.template.TemplateConfig;
import cn.hutool.extra.template.TemplateEngine;
import cn.hutool.extra.template.TemplateUtil;
import com.himiotech.core.framework.config.HimioConfig;
import com.himiotech.core.framework.helper.constant.GenConstants;
import com.himiotech.core.framework.helper.utils.SpringUtils;
import com.himiotech.core.project.data.dao.JdbcDao;
import com.himiotech.core.project.model.entity.gen.GenTable;
import com.himiotech.core.project.model.entity.gen.GenTableColumn;
import com.himiotech.core.project.service.IGenTableService;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.util.*;

/**
 * 模板类生成配置工具类
 * 主要是获取一些参数
 *
 * @author wuwenbin
 **/
@Slf4j
public class TplUtils {

    /**
     * 根据列类型获取导入包
     *
     * @param genTable 业务表对象
     * @return 返回需要导入的包列表
     */
    public static HashSet<String> getImportList(GenTable genTable) {
        List<GenTableColumn> columns = genTable.getColumns();
        GenTable subGenTable = genTable.getSubTable();
        HashSet<String> importList = new HashSet<>();
        if (ObjectUtil.isNotNull(subGenTable)) {
            importList.add("java.util.List");
        }
        for (GenTableColumn column : columns) {
            if (!column.isSuperColumn() && GenConstants.TYPE_DATE.equals(column.getJavaType())) {
                importList.add("java.util.Date");
                importList.add("com.fasterxml.jackson.annotation.JsonFormat");
            } else if (!column.isSuperColumn() && GenConstants.TYPE_BIGDECIMAL.equals(column.getJavaType())) {
                importList.add("java.math.BigDecimal");
            }
        }
        return importList;
    }

    public static Map<String, String> genTpls(GenTable table) {
        String[] paths = {"beetl/java", "beetl/static"};
        String[] tpls = {"metadata.java.btl", "entity.java.btl", "mapper.java.btl", "service.java.btl", "serviceImpl.java.btl", "controller.java.btl"};
        String[] tpls2 = {"page.html.btl", "page.js.btl"};
        Map<String, String> resultData = new HashMap<>(8);
        for (String path : paths) {
            TemplateConfig templateConfig = new TemplateConfig();
            templateConfig.setPath(path);
            templateConfig.setResourceMode(TemplateConfig.ResourceMode.CLASSPATH);
            TemplateEngine engine = TemplateUtil.createEngine(templateConfig);
            Dict dict = Dict.create().set("table", table).set("importList", getImportList(table));
            if (path.endsWith("java")) {
                genByTpl(dict, tpls, resultData, engine);
            } else {
                genByTpl(dict, tpls2, resultData, engine);
            }
        }
        return resultData;
    }

    /**
     * 获取权限前缀
     *
     * @param moduleName   模块名称
     * @param businessName 业务名称
     * @return 返回权限前缀
     */
    public static String getPermissionPrefix(String moduleName, String businessName) {
        return StrUtil.format("{}:{}", moduleName, businessName);
    }


    /**
     * 获取代码生成地址
     *
     * @param table    业务表信息
     * @param template 模板文件名
     * @return 生成地址
     */
    public static String getGenPathSimple(GenTable table, String template) {
        String resource = table.getPackageName().replace(".", File.separator);
        String prePath = "";
        if (template.endsWith("java")) {
            if (template.startsWith("Entity")) {
                prePath = "model" + File.separator + "entity" + File.separator;
                template = ".java";
            } else if (template.startsWith("Metadata")) {
                prePath = "model" + File.separator + "metadata" + File.separator;
            } else if (template.startsWith("Mapper")) {
                prePath = "data" + File.separator + "mapper" + File.separator;
            } else if (template.startsWith("Service")) {
                if (template.startsWith("ServiceImpl")) {
                    prePath = "service" + File.separator + "impl" + File.separator;
                } else {
                    prePath = "service" + File.separator + "I";
                }
            } else if (template.startsWith("Controller")) {
                prePath = "controller" + File.separator;
            }
            return System.getProperty("user.dir") +
                    File.separator + "src" + File.separator + "main" + File.separator + "java" +
                    File.separator + resource + File.separator + table.getBusinessName() +
                    File.separator + prePath + table.getClassName() + template;
        } else {
            if (template.endsWith(".js")) {
                return HimioConfig.getStaticPathStatic() + File.separator +
                        "assets" + File.separator + "business" + File.separator +
                        "js" + File.separator + StrUtil.lowerFirst(table.getClassName()) + ".js";
            } else {
                return HimioConfig.getWebappPathStatic() + File.separator +
                        table.getModuleName() + File.separator + table.getBusinessName() + ".html";
            }
        }
    }

    /**
     * 新增菜单
     *
     * @param table
     */
    public static void executeSql(GenTable table) throws Exception {
        String path = "beetl/sql";
        String menuTpl = "menu.sql.btl";
        String buttonTpl = "button.sql.btl";

        Map<String, String> resultData = new HashMap<>(2);
        TemplateConfig templateConfig = new TemplateConfig();
        templateConfig.setPath(path);
        templateConfig.setResourceMode(TemplateConfig.ResourceMode.CLASSPATH);
        TemplateEngine engine = TemplateUtil.createEngine(templateConfig);

        Dict dict = Dict.create().set("table", table);
        genByTpl(dict, new String[]{menuTpl}, resultData, engine);

        IGenTableService genTableService = SpringUtils.getBean(IGenTableService.class);
        GenTable genTable = genTableService.selectGenTableById(table.getTableId());
        if (genTable.getSqlInsert() == null || genTable.getSqlInsert() != 1) {
            //菜单权限
            String menuSql = resultData.get("Menu.sql");
            JdbcDao jdbcDao = SpringUtils.getBean(JdbcDao.class);
            log.info("插入菜单 SQL：{}", menuSql);
            long parentId = jdbcDao.insertMapAutoGenKeyReturnKey(menuSql, Collections.emptyMap());
            resultData.clear();

            //按钮权限
            dict.set("parentId", parentId);
            genByTpl(dict, new String[]{buttonTpl}, resultData, engine);
            String buttonSql = resultData.get("Button.sql");
            String[] btnSqls = buttonSql.split(";");
            for (String btnSql : btnSqls) {
                log.info("插入按钮 SQL：{}", btnSql);
                jdbcDao.executeArray(btnSql);
            }
            //更新插入状态
            genTableService.updateById(new GenTable().setSqlInsert(1).setTableId(table.getTableId()));
        }

    }

    public static Map<String, String> genMapper(Dict dict) {
        TemplateConfig templateConfig = new TemplateConfig();
        templateConfig.setPath("beetl/dataScope");
        templateConfig.setResourceMode(TemplateConfig.ResourceMode.CLASSPATH);
        TemplateEngine engine = TemplateUtil.createEngine(templateConfig);
        Template template = engine.getTemplate("mapper.xml.btl");
        String mapper = template.render(dict);
        Map<String, String> resultMap = new HashMap<>(2);
        resultMap.put("mapper", mapper);
        Template template1 = engine.getTemplate("servicePart.java.btl");
        String servicePart = template1.render(dict);
        resultMap.put("service", servicePart);
        return resultMap;
    }

    private static void genByTpl(Dict dict, String[] tpls, Map<String, String> resultData, TemplateEngine engine) {
        for (String tpl : tpls) {
            Template template = engine.getTemplate(tpl);
            String result = template.render(dict);
            String classFile = StrUtil.upperFirst(tpl).replace(".btl", "");
            resultData.put(classFile, result);
        }
    }
}
